/*
 *  Copyright 2008 Mark Ashworth <javameme@gmail.com>.
 * 
 *  Licensed under the GNU General Public License v3 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.gnu.org/licenses/gpl-3.0.html
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 */
package xperiment.metaphor.persistence.hibernate;

import xperiment.metaphor.model.AbstractSpringJUnit;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.springframework.dao.DataIntegrityViolationException;
import xperiment.metaphor.model.entity.Gender;
import xperiment.metaphor.model.entity.Person;
import xperiment.metaphor.model.entity.PopulationGroup;
import xperiment.metaphor.model.entity.User;
import xperiment.metaphor.model.Queries;
import xperiment.metaphor.persistence.filter.SearchCriteria;

/**
 *
 * @author Mark Ashworth <javameme@gmail.com>
 * @version 1.0.0
 */
public class HibernateUserDaoTest extends AbstractSpringJUnit {
         
    public HibernateUserDaoTest(String testName) {
        super(testName);
    }            
        
    /**
     * persist
     */
    public void testPersist() {
        logger.info("persist");
        
//        User user = new User("markash", "password");
//        
//        try {
//            user = (User) getDao().persist(user);
//            logger.info("Persisted user: {}", user);
//            assertTrue(user.getId() != null);
//            assertTrue(user.getId().longValue() > 0);
//            assertEquals("markash", user.getUsername());
//            assertEquals("password", user.getPassword());
//            assertTrue(user.isEnabled());
//            assertTrue(user.getRoles() != null);
//            assertTrue(user.getRoles().size() == 0);
//         } finally {
//            if (user.getId() != null) {
//                getDao().delete(user);
//            }
//        }
    }
    
    /**
     * persist
     */
    public void testPersistXML() throws Exception {
        logger.info("persistXML");
        
        String xml = "<users>"
                +"<users user_id='-1' username='kima' password='test' enabled='true' />"
                +"<users user_id='-1' username='crystala' password='test' enabled='true' />"
                +"<users user_id='-1' username='michaela' password='test' enabled='true' />"
                +"</users>";
        
        DocumentFactory factory = DocumentFactory.getInstance();
        SAXReader reader = new SAXReader(factory);
        Document doc = reader.read(new StringReader(xml));
        List<Element> nodes = doc.selectNodes("//user_login");
        
        List<User> users = new ArrayList<User>();
        for (Element node : nodes) {
            users.add((User) getDao().persist(User.class, node.asXML()));
        }
        
        for (User user : users) {
            logger.info("Persisted user: {}", user);
        }
    }
    
    /**
     * persist
     */
    public void testPersistUnique() throws Exception {
        logger.info("persistUnique");
        
        User user = new User("markash", "password");
        User another = new User("Karkash", "password");
        
        try {
            user = (User) getDao().persist(user);
            another = (User) getDao().persist(another);
            
            /*Try to make Karkash into Markash*/
            another.setUsername("markash");
            try {
                another = (User) getDao().persist(another);
                fail("A unique user exception should have been thrown");
            } catch (DataIntegrityViolationException e) {
                /*Pass*/
            }
         } finally {
            if (user.getId() != null) {
                getDao().delete(user);
            }
            if (another.getId() != null) {
                getDao().delete(another);
            }
        }
    }
    

    /**
     * Test of retrieve method, of class HibernateUserDao.
     */
    public void testSearchCriteria() throws Exception {
        System.out.println("retrieve(SearchCriteria)");
        
        User[] users = new User[] {
            new User("user1", "password"),
            new User("user2", "password"),
            new User("user3", "password"),
            new User("user4", "password"),
            new User("user5", "password"),
            new User("user6", "password"),
            new User("user7", "password"),
            new User("user8", "password"),
            new User("user9", "password"),
            new User("user10", "password"),
            new User("user11", "password"),
            new User("user12", "password"),
            new User("user13", "password"),
            new User("user14", "password"),
            new User("user15", "password"),
            new User("user16", "password"),
            new User("user17", "password"),
            new User("user18", "password"),
            new User("user19", "password"),
            new User("user20", "password")
        };
        
        try {
            for (int i = 0; i < users.length; i++) {
                users[i] = (User) getDao().persist(users[i]);
            }

            SearchCriteria searchCriteria = 
                    SearchCriteria.forClass(User.class)
                    .search("s")
                    .pageSize(5)
                    .asc("id");

            List<User> results = (List<User>) getDao().retrieve(searchCriteria);
            assertEquals(5, results.size());
            for (int i = 0; i < results.size(); i++) {
                assertEquals(users[i].getUsername(), results.get(i).getUsername());
            }
            
            searchCriteria.incrementPage();
            results = getDao().retrieve(searchCriteria);
            assertEquals(5, results.size());
            for (int i = 0; i < results.size(); i++) {
                assertEquals(users[5 + i].getUsername(), results.get(i).getUsername());
            }
            
            searchCriteria.incrementPage();
            results = getDao().retrieve(searchCriteria);
            assertEquals(5, results.size());
            for (int i = 0; i < results.size(); i++) {
                assertEquals(users[10 + i].getUsername(), results.get(i).getUsername());
            }
            
            searchCriteria.incrementPage();
            results = getDao().retrieve(searchCriteria);
            assertEquals(5, results.size());
            for (int i = 0; i < results.size(); i++) {
                assertEquals(users[15 + i].getUsername(), results.get(i).getUsername());
            }
            
            searchCriteria.setPaged(false);
            results = getDao().retrieve(searchCriteria);
            assertEquals(users.length, results.size());
            for (int i = 0; i < results.size(); i++) {
                assertEquals(users[i].getUsername(), results.get(i).getUsername());
            }
            
        } finally {
            for (User user : users) {
                try {
                    getDao().delete(user);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        }
    }
//
//    /**
//     * Test of retrieve method, of class HibernateUserDao.
//     */
//    public void testRetrieve_Query() throws Exception {
//        System.out.println("retrieve");
//        Query query = null;
//        HibernateUserDao instance = new HibernateUserDao();
//        Collection<User> expResult = null;
//        Collection<User> result = instance.retrieve(query);
//        assertEquals(expResult, result);
//        // TODO review the generated test code and remove the default call to fail.
//        fail("The test case is a prototype.");
//    }
//
//    /**
//     * Test of retrieveById method, of class HibernateUserDao.
//     */
//    public void testRetrieveById() {
//        System.out.println("retrieveById");
//        long id = 0L;
//        HibernateUserDao instance = new HibernateUserDao();
//        User expResult = null;
//        User result = instance.retrieveById(id);
//        assertEquals(expResult, result);
//        // TODO review the generated test code and remove the default call to fail.
//        fail("The test case is a prototype.");
//    }
//
//    /**
//     * Test of retrieveByName method, of class HibernateUserDao.
//     */
//    public void testRetrieveByName() {
//        System.out.println("retrieveByName");
//        String name = "";
//        HibernateUserDao instance = new HibernateUserDao();
//        User expResult = null;
//        User result = instance.retrieveByName(name);
//        assertEquals(expResult, result);
//        // TODO review the generated test code and remove the default call to fail.
//        fail("The test case is a prototype.");
//    }
//
    /**
     * 
     */
    public void testPersistNew() throws Exception {
        logger.info("persist new");
        
        Date lastLoggedOn = new Date();
        
        Gender gender = null;
        List genders = getDao().retrieve(Queries.GENDER_MALE.getQuery());
        if (genders == null || genders.size() == 0) {
            gender = new Gender("MALE");
            gender = (Gender) getDao().persist(gender);
        } else {
            gender = (Gender) genders.get(0);
        }
        
        PopulationGroup group = null;
        List groups = getDao().retrieve(Queries.POPULATION_GROUP_WHITE.getQuery());
        if (groups == null || groups.size() == 0) {
            group = new PopulationGroup("WHITE");
            group = (PopulationGroup) getDao().persist(group);
        } else {
            group = (PopulationGroup) groups.get(0);
        }
        
        Person person = new Person("Mark", "Ashworth");
        person.setGender(gender);
        person.setDateOfBirth(new Date(1974-1900, 5-1, 31));
        person.setIdentityNo("735445437");
        person.setInitials("P");
        person.setPopulationGroup(group);
        
//        User user = new User("marka", "password");
//        user.setIPAddress("1");
//        user.setLastIPAddress("2");
//        user.setLastLoggedOn(lastLoggedOn);
//        user.setLoggedOn(lastLoggedOn);
//        user.setSession("3");
//        user.setEnabled(true);
//        user.setPerson(person);
//        
//        user = (User) getDao().persist(user);
//        
//        assertNotNull(user);
//        assertTrue("The user.id must be greater than 0", user.getId() > 0);
//        assertEquals("marka", user.getUsername());
//        assertEquals("password", user.getPassword());
//        assertEquals("1", user.getIPAddress());
//        assertEquals("2", user.getLastIPAddress());
//        assertEquals("3", user.getSession());
//        assertEquals(lastLoggedOn, user.getLastLoggedOn());
//        assertEquals(lastLoggedOn, user.getLoggedOn());
//        assertEquals(true, user.isEnabled());
//        
//        assertNotNull(user.getPerson());
//        assertEquals("Mark", user.getPerson().getFirstName());
//        assertEquals("Ashworth", user.getPerson().getLastName());
//        assertEquals("P", user.getPerson().getInitials());
//        assertEquals("735445437", user.getPerson().getIdentityNo());
//        
//        assertNotNull(user.getPerson().getPopulationGroup());
//        assertEquals("WHITE", user.getPerson().getPopulationGroup().getName());
//        
//        assertNotNull(user.getPerson().getGender());
//        assertEquals("MALE", user.getPerson().getGender().getName());
    }

    /**
     * 
     */
    public void testPersistUpdate() throws Exception {
        logger.info("persist update");
        
        Date lastLoggedOn = new Date();
        
        Gender gender = null;
        List genders = getDao().retrieve(Queries.GENDER_MALE.getQuery());
        if (genders == null || genders.size() == 0) {
            gender = new Gender("MALE");
            gender = (Gender) getDao().persist(gender);
        } else {
            gender = (Gender) genders.get(0);
        }
        
        PopulationGroup group = null;
        List groups = getDao().retrieve(Queries.POPULATION_GROUP_WHITE.getQuery());
        if (groups == null || groups.size() == 0) {
            group = new PopulationGroup("WHITE");
            group = (PopulationGroup) getDao().persist(group);
        } else {
            group = (PopulationGroup) groups.get(0);
        }
        
        Person person = new Person("Mark", "Ashworth");
        person.setGender(gender);
        person.setDateOfBirth(new Date(1974-1900, 5-1, 31));
        person.setIdentityNo("735445437");
        person.setInitials("P");
        person.setPopulationGroup(group);
        
//        User user = new User("marka", "password");
//        user.setIPAddress("1");
//        user.setLastIPAddress("2");
//        user.setLastLoggedOn(lastLoggedOn);
//        user.setLoggedOn(lastLoggedOn);
//        user.setSession("3");
//        user.setEnabled(true);
//        user.setPerson(person);
//        
//        user = (User) getDao().persist(user);
//        
//        assertNotNull(user);
//        assertTrue("The user.id must be greater than 0", user.getId() > 0);
//        assertEquals("marka", user.getUsername());
//        assertEquals("password", user.getPassword());
//        assertEquals("1", user.getIPAddress());
//        assertEquals("2", user.getLastIPAddress());
//        assertEquals("3", user.getSession());
//        assertEquals(lastLoggedOn, user.getLastLoggedOn());
//        assertEquals(lastLoggedOn, user.getLoggedOn());
//        assertEquals(true, user.isEnabled());
//        
//        assertNotNull(user.getPerson());
//        assertEquals("Mark", user.getPerson().getFirstName());
//        assertEquals("Ashworth", user.getPerson().getLastName());
//        assertEquals("P", user.getPerson().getInitials());
//        assertEquals("735445437", user.getPerson().getIdentityNo());
//        
//        assertNotNull(user.getPerson().getPopulationGroup());
//        assertEquals("WHITE", user.getPerson().getPopulationGroup().getName());
//        
//        assertNotNull(user.getPerson().getGender());
//        assertEquals("MALE", user.getPerson().getGender().getName());
//        
//        
//        user.setPassword("test");
//        user = (User) getDao().persist(user);
//        
//        assertNotNull(user);
//        assertEquals("test", user.getPassword());
    }
}
